import smtplib

from email.mime.text import MIMEText
from email.header import Header
from email.utils import formataddr


class EmailSender(object):
    def __init__(self, email_settings: dict, authentication: tuple = None, method=None):
        self.email_settings = email_settings
        smtp_method = smtplib.SMTP
        if method == 'SSL':
            smtp_method = smtplib.SMTP_SSL  # type: ignore
        self.smtp = smtp_method(
            host=email_settings.get('server_host'),
            port=email_settings.get('server_port'),
            timeout=30
        )
        if method == 'TTL':
            self.smtp.starttls()
        if authentication:
            self.smtp.login(*authentication)

    def send(self, template_path, args: dict):
        msg = EmailTemplate(template_path).format(args)
        to_addrs = args.get('to', [])
        self.smtp.sendmail(self.email_settings.get('sender'), to_addrs, msg)


class EmailTemplate(object):
    def __init__(self, template_path: str):
        with open(template_path, encoding='utf-8') as f:
            template = f.read()

        self.template = template

    def format(self, args):
        template = self.template
        for k, v in args.get('body', {}).items():
            template = template.replace(k, str(v))

        mimetext = MIMEText(template, 'html', 'utf-8')
        mimetext['From'] = formataddr(('', args.get('from', '')))
        mimetext['Subject'] = Header(args.get('title', ''), 'utf-8')
        mimetext['To'] = ','.join(
            [formataddr(('', item)) for item in args.get('to', [])]
        )

        return mimetext.as_string()
